package com.chuangsi.project.wechat;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.chuangsi.common.exception.ServiceException;
import com.chuangsi.common.utils.Assert;
import com.chuangsi.common.utils.ConfigUtil;
import com.chuangsi.framework.config.WxPayConfig;
import com.chuangsi.project.admin.domain.Agreement;
import com.chuangsi.project.admin.domain.PayOrder;
import com.chuangsi.project.admin.domain.Seal;
import com.chuangsi.project.admin.dto.app.order.ResPlaceAnOrderDto;
import com.chuangsi.project.admin.service.SealService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.RSAPublicKeyNotificationConfig;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Component
@Slf4j
public class PayUtil {
    @Autowired
    private ConfigUtil configUtil;
    @Autowired
    private WxPayConfig wxPayConfig;
    @Autowired
    private SealService sealService;

    //用于存放每个印章的支付配置
    public static Map<String,Config> CONFIG_MAP = new HashMap<>();
    //用于存放每个印章的支付回调配置
    public static Map<String,NotificationConfig> NOTIFICATION_CONFIG_MAP = new HashMap<>();


    @PostConstruct
    public void initConfig(){
        log.info("<<<<<-----加载微信支付证书开始----->>>>>");
        List<Seal> sealList = sealService.list();
        String profilesActive = configUtil.getProfilesActive();
        CONFIG_MAP.clear();
        NOTIFICATION_CONFIG_MAP.clear();
        for (Seal seal : sealList) {
            //全配置好了，才可以加载微信支付证书
            if(StrUtil.isNotBlank(seal.getMchId()) && StrUtil.isNotBlank(seal.getPublicKeyPath()) && StrUtil.isNotBlank(seal.getPrivateKeyPath()) && StrUtil.isNotBlank(seal.getPublicKeyId()) && StrUtil.isNotBlank(seal.getMerchantSerialNumber()) && StrUtil.isNotBlank(seal.getApiV3Key())){
                String publicKeyPath  = "";
                String privateKeyPath = "";
                if(profilesActive.equals("dev")){
                    publicKeyPath = "src\\main\\resources\\cert\\"+seal.getMchId()+"\\pub_key.pem";
                    privateKeyPath ="src\\main\\resources\\cert\\"+seal.getMchId()+"\\apiclient_key.pem";
                }else {
                    publicKeyPath = seal.getPublicKeyPath();
                    privateKeyPath = seal.getPrivateKeyPath();
                }
                log.info("--------------------------------------------------------------");
                log.info("商户号：{}，公钥证书地址：{}",seal.getSealName(),publicKeyPath);
                log.info("商户号：{}，私钥证书地址：{}",seal.getSealName(),privateKeyPath);
                log.info("--------------------------------------------------------------");
                // 使用自动更新平台证书的RSA配置
                Config config = new RSAPublicKeyConfig.Builder()
                        .merchantId(seal.getMchId())
                        .publicKeyFromPath(publicKeyPath)
                        .privateKeyFromPath(privateKeyPath)
                        .publicKeyId(seal.getPublicKeyId()) //微信支付公钥ID
                        .merchantSerialNumber(seal.getMerchantSerialNumber())
                        .apiV3Key(seal.getApiV3Key())
                        .build();
                CONFIG_MAP.put(seal.getSealId(),config);

                // 1. 如果你使用的是微信支付公私钥，则使用 RSAPublicKeyNotificationConfig
                NotificationConfig notificationConfig = new RSAPublicKeyNotificationConfig.Builder()
                        .publicKeyFromPath(publicKeyPath)
                        .publicKeyId(seal.getPublicKeyId())
                        .apiV3Key(seal.getApiV3Key())
                        .build();
                NOTIFICATION_CONFIG_MAP.put(seal.getPublicKeyId(),notificationConfig);
            }
        }
        log.info("<<<<<-----加载微信支付证书结束----->>>>>");
    }

    public static NotificationConfig getNotificationConfig(String serial) {
        return NOTIFICATION_CONFIG_MAP.get(serial);
    }

    public ResPlaceAnOrderDto jsapi(PayOrder payOrder,String openId, Seal seal) {
        if(StrUtil.isBlank(openId)){
            throw new ServiceException("没有openId不能发起支付");
        }
        Config config = CONFIG_MAP.get(seal.getSealId());
        Assert.notNull(config,"未找到支付配置");
        // 构建service
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(config).build();
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal((payOrder.getFee().multiply(BigDecimal.valueOf(100))).intValue());
        request.setAmount(amount);
        Payer payer = new Payer();
        payer.setOpenid(openId);
        request.setPayer(payer);
        request.setAppid(wxPayConfig.getAppId());
        request.setNotifyUrl(wxPayConfig.getNotifyUrl());
        request.setMchid(seal.getMchId());
        request.setDescription("非车险");
        request.setOutTradeNo(payOrder.getOutTradeNo());
        log.info("微信openid:{}",openId);
        log.info("微信appid:{}",wxPayConfig.getAppId());
        log.info("微信商户号:{}",seal.getMchId());
        log.info("微信支付回调:{}",wxPayConfig.getNotifyUrl());
        log.info("微信支付订单号:{}",payOrder.getOutTradeNo());
        // 调用下单方法，得到应答
        try {
            PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
            return new ResPlaceAnOrderDto(payOrder.getPayOrderId(),response);
        }catch (com.wechat.pay.java.core.exception.ServiceException e){
            e.printStackTrace();
            throw new ServiceException("微信支付失败:"+e.getErrorMessage());
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("微信支付失败");
        }
    }



//    public Map<String,Object> jsapi(Order order, String openId){
//        if(StrUtil.isBlank(openId)){
//            throw new ServiceException("没有openId不能发起支付");
//        }
//        // 构建service
//        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(config).build();
//        PrepayRequest request = new PrepayRequest();
//        Amount amount = new Amount();
//        amount.setTotal((order.getFee().multiply(BigDecimal.valueOf(100))).intValue());
//        request.setAmount(amount);
//        Payer payer = new Payer();
//        payer.setOpenid(openId);
//        request.setPayer(payer);
//        request.setAppid(wxPayConfig.getAppId());
//        request.setMchid(wxPayConfig.getMchId());
//        request.setDescription(enterpriseBusinessService.getTypeName(order.getType()));
//        request.setNotifyUrl(wxPayConfig.getNotifyUrl());
//        request.setOutTradeNo(order.getOutTradeNo());
//        // 调用下单方法，得到应答
//        try {
//            PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
//            Map<String,Object> param = new HashMap<>();
//            param.put("package", response.getPackageVal());
//            param.put("nonceStr", response.getNonceStr());
//            param.put("timeStamp", response.getTimeStamp());
//            param.put("paySign", response.getPaySign());
//            param.put("signType", response.getSignType());
//            return param;
//        }catch (com.wechat.pay.java.core.exception.ServiceException e){
//            e.printStackTrace();
//            throw new ServiceException("微信支付失败:"+e.getErrorMessage());
//        }catch (Exception e){
//            e.printStackTrace();
//            throw new ServiceException("微信支付失败");
//        }
//    }
//
//
//    public CreateRequest refund(Order order){
//        // 初始化服务
//        RefundService service = new RefundService.Builder().config(config).build();
//        CreateRequest request = new CreateRequest();
//        try {
//            AmountReq amount = new AmountReq();
//            amount.setTotal(order.getFee().multiply(BigDecimal.valueOf(100)).longValue());
//            amount.setRefund(order.getFee().multiply(BigDecimal.valueOf(100)).longValue());
//            amount.setCurrency("CNY");
//            request.setAmount(amount);
//            request.setOutTradeNo(order.getOutTradeNo());
//            request.setOutRefundNo(UUID.fastUUID().toString().replaceAll("-",""));
//            Refund response = service.create(request);
//            log.info("退款支付返回",response.toString());
//            return request;
//        } catch (HttpException e) { // 发送HTTP请求失败
//            e.printStackTrace();
//            throw new ServiceException("退款失败");
//            // 调用e.getHttpRequest()获取请求打印日志或上报监控，更多方法见HttpException定义
//        } catch (ServiceException e) { // 服务返回状态小于200或大于等于300，例如500
//            e.printStackTrace();
//            throw new ServiceException("退款失败：返回体打印日志或上报监控");
//            // 调用e.getResponseBody()获取返回体打印日志或上报监控，更多方法见ServiceException定义
//        } catch (MalformedMessageException e) { // 服务返回成功，返回体类型不合法，或者解析返回体失败
//            e.printStackTrace();
//            throw new ServiceException("退款失败：解析返回体失败");
//            // 调用e.getMessage()获取信息打印日志或上报监控，更多方法见MalformedMessageException定义
//        }
//    }


}
